
#include <BLibrary>
#include "member_BLibrary.h"

using namespace BWE;

#define member					(*(member_BLibrary*)_ptr)
#define member_allocate()		_ptr = new member_BLibrary(this)
#define member_release()		delete (member_BLibrary*)_ptr

BString BLibrary::LibPath(const BString& libName)
{
	BString path;
	LibPath(path, libName);
	return path;
}
bool BLibrary::LibPath(BString& path, const BString& libName)
{
	path.reset();

#ifdef linux
	char pathbuff[256];
	if (void* handle = dlopen(libName.cstr(), RTLD_NOW))
	{
		int ret = dlinfo(handle, RTLD_DI_ORIGIN, pathbuff);
		if (ret == 0)
		{
			path = pathbuff;
		}
	}
#endif

#ifdef _WIN32
	WCHAR pathbuff[256];
	bMbsToWcs(libName.cstr(), pathbuff);
	HMODULE module = GetModuleHandle(pathbuff);
	DWORD len = GetModuleFileName(module, pathbuff, 256);
	if (len > 0)
	{
		char cstr[256];
		bWcsToMbs(pathbuff, cstr);
		path = cstr;
		path.replace('\\', '/');
		path -= '/';
	}
#endif

	if (path.size())
	{
		path -= libName.name();
		return true;
	}
	
	return false;
}

BLibrary::BLibrary()
{
	member_allocate();
}
BLibrary::BLibrary(const BString& fileName)
{
	member_allocate();
	member.fileName = fileName;
}
BLibrary::~BLibrary()
{
	member.unload();
	member_release();
}

void BLibrary::setFileName(const BString& fileName)
{
	if (member.fileName != fileName)
	{
		member.unload();
		member.fileName = fileName;
		if (this->checks(Signal_FileNameChanged))
			this->emit(Signal_FileNameChanged, fileName);
	}
}
const BString& BLibrary::fileName() const
{
	return member.fileName;
}

bool BLibrary::load()
{
	member.load();
	return isLoaded();
}
bool BLibrary::load(const BString& libName)
{
	member.unload();
	member.fileName = libName;
	return load();
}
bool BLibrary::unload()
{
	return member.unload();
}

bool BLibrary::isLoaded()
{
	return member.handle != 0;
}

void* BLibrary::get(const BString& slotName)
{
	if (slotName.empty())
		return 0;
	return member.address(slotName.cstr());
}

